package image;

import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.IntBuffer;

import javax.media.opengl.GL2;
/**A class to handle GLSL shader loading from glsl files.*/
public class ShaderLoader
	{
	/**Load and compile the given GLSL vertex/fragment shaders into a shader program, which is returned.
	 * The shader is compiled on the indicated GL.*/
	public int loadShaderFromFile(GL2 gl, String vFile, String fFile) throws IOException 
		{
		GLErrors.check(gl, "Purge: loadShader: "+vFile+", "+fFile);
		
		String vString = Calc.readFileString(new FileInputStream(vFile));
		final int vShader = gl.glCreateShader(GL2.GL_VERTEX_SHADER);
		gl.glShaderSource(vShader, 1, new String[]{vString}, new int[]{vString.length()},0);
		gl.glCompileShader(vShader);
		vString = null;
		GLErrors.check(gl, "Vertex shader: "+vFile);
		
		String fString = Calc.readFileString(new FileInputStream(fFile));
		final int fShader = gl.glCreateShader(GL2.GL_FRAGMENT_SHADER);
		gl.glShaderSource(fShader, 1, new String[]{fString}, new int[]{fString.length()},0);
		gl.glCompileShader(fShader);
		fString = null;
		GLErrors.check(gl, "Fragment shader: "+fFile);
		
		final int shaderProgram = gl.glCreateProgram();
		gl.glAttachShader(shaderProgram, vShader);
		gl.glAttachShader(shaderProgram, fShader);
		gl.glLinkProgram(shaderProgram);
		gl.glValidateProgram(shaderProgram);
		
		int[] status = new int[1];
	    gl.glGetProgramiv(shaderProgram, GL2.GL_LINK_STATUS, status, 0);
	    if (status[0] != 1) 
	    	{
	    	int[] logSize = new int[1];
	        gl.glGetProgramiv(shaderProgram, GL2.GL_INFO_LOG_LENGTH, logSize, 0);
	        int size = logSize[0];
	        System.err.println("Program link error: ");
	        if (size > 0) {
	            ByteBuffer byteBuffer = ByteBuffer.allocate(size);
	            IntBuffer none = IntBuffer.allocate(1);
	            gl.glGetProgramInfoLog(shaderProgram, size, none, byteBuffer);
	            for (byte b : byteBuffer.array()) 
	            	{
	                System.err.print((char) b);
	            	}
	        } 
	        else 
	        	{
	            System.out.println("Unknown");
	        	}
	        return -1;
	    	}
		
		//Delete shader objects; The binary will be kept in the program object.
		gl.glDeleteShader(vShader);
		gl.glDeleteShader(fShader);
		if(GLErrors.check(gl, "GLSL Shader Program: "+vFile+", "+fFile))
			return -1;
		
		return shaderProgram;
		}
	}
